//
//  ViewController.swift
//  TestAPIManager
//
//  Created by 杨庆 on 2020/9/28.
//  Copyright © 2020 杨庆. All rights reserved.
// RxSwift、Alamofire、Moya和HandyJson的结合使用 (https://luodecoding.github.io/2019/04/19/SwiftNetWorkWith-MoyaAndHandyJson/)

import UIKit
import Moya
import RxSwift
import RxCocoa

class ViewController: UIViewController {
    
    private let miniUsernameLength = 5
    private let miniPasswordLength = 5
    
    @IBOutlet weak var usernameOutlet: UITextField!
    @IBOutlet weak var usernameValidOutlet: UILabel!
    @IBOutlet weak var passwordOutlet: UITextField!
    @IBOutlet weak var passwordValidOutlet: UILabel!
    @IBOutlet weak var dosomethingButton: UIButton!
    @IBOutlet weak var testTableVButtonOutlet: UIButton!
    @IBOutlet weak var indexLabel: UILabel!

    var disposeBag = DisposeBag()
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        indexLabel.isHidden = true
    }

    override func viewDidLoad() {
        super.viewDidLoad()
     
        testTextField()
    }
}



extension ViewController {

    @IBAction func relativeWmsAction() {
        navigationController?.pushViewController(RelativeWMSController(), animated: true)
    }
    
}


extension ViewController {
    
    /* 计时功能 */
    func interval() {
        let observable = Observable<Int>
            .interval(1, scheduler: MainScheduler.instance)
        
        // 方式一
        //        observable
        //            .map{"当前索引值:\($0)"}
        //            .bind(to:indexLabel.rx.text)
        //            .disposed(by: disposeBag)
        
        // 方式二
        observable
            .map{"当前索引值:\($0)"}
            .bind{ [weak self] text in
                self?.indexLabel.text = text
        }
        .disposed(by: disposeBag)
    }
    
    
    /* 测试输入框输入对底部点击按钮的 enable 判断 */
    func testTextField() {
        usernameValidOutlet.text = "用户名至少 \(miniUsernameLength)位"
        passwordValidOutlet.text = "密码至少 \(miniPasswordLength)位"

        
        // ===================== userName ================
        
        /*!
         * Observable  被观察对象
         * Observer    观察者
         - Rx 中 observer 订阅一个 observable 对象
         */
        
        /*!
         - map: 将可观察序列的每个元素投射到一个新的形式中
         - share: 返回一个事件序列,监听底层的事件,通知自己的订阅者们
         - shareReplay 作用: 让他们共享一个源,而不是单独创建新的源.这样可以
         减少不必要的开支.
         - disposeBag 作用: 和对象一样,每一个绑定也有生命周期.并且这个绑定可
         被清除的. dispose(by:disposeBag)就是将绑定的声明周期交给 disposeBag
         管理.当 disposeBag 被释放的时候,内部尚未清除的绑定也就被清除了.
         (有点类似于 ARC 来管理绑定的声明周期)
         */
        
        let usernameValid = usernameOutlet.rx.text.orEmpty
            .map {$0.count >= self.miniUsernameLength} // 通过一个转换函数,将每个元素转换一遍,然后返回
            .share(replay:1)
        
        /* `a` 订阅 `b`
         *  a: usernameValidOutlet(UILabel) 是一个'观察者' observer,
         *  b: 订阅 usernameValid (obserable<Bool>) 这个 observable '被观察者'
         */
        
        usernameValid
            .bind(to:usernameValidOutlet.rx.isHidden)
            .disposed(by: disposeBag)
        
        usernameValid
            .bind(to:passwordOutlet.rx.isEnabled)
            .disposed(by: disposeBag)
        
        
        // ================== password =================
        
        
        let passwordValid = passwordOutlet.rx.text.orEmpty
            .map{ $0.count >= self.miniPasswordLength }
            .share(replay:1)
        
        passwordValid
            .bind(to: passwordValidOutlet.rx.isHidden)
            .disposed(by: disposeBag)
        
        
        // 都满足条件底部按钮可点击
        
        let everythingValid = Observable.combineLatest(
            usernameValid,
            passwordValid){ $0 && $1 }
            .share(replay: 1)
        
        everythingValid
            .bind(to:self.dosomethingButton.rx.isEnabled)
            .disposed(by: disposeBag)
        
        
        // 底部按钮点击
        dosomethingButton.rx.tap
            .subscribe(onNext:{[weak self] in
                self?.showAlert()
            })
            .disposed(by: disposeBag)
        
        
        func presentVc() {
            let simpleVc = SimpleViewController()
            let nav = UINavigationController(rootViewController: simpleVc)
            nav.modalPresentationStyle = .fullScreen
            self.present(nav, animated: true, completion: nil)
        }
        
        testTableVButtonOutlet.rx.tap
            .subscribe(onNext:{
                presentVc()
            })
            .disposed(by: disposeBag)
        
    }
    
    
    
    /// 跳转测试 RxSwift 使用控制器
    /// - Parameter sender: 按钮
    @IBAction func testRxSwift(_ sender: Any) {
        let rxSwiftVC = RxSwiftController()
        rxSwiftVC.modalPresentationStyle = .fullScreen
        present(rxSwiftVC, animated: true, completion: nil)
    }
    
    func showAlert() {
        let alertView = UIAlertView (
            title: "RxExample",
            message: "This is wonderful",
            delegate: nil,
            cancelButtonTitle: "OK"
        )
        alertView.show()
    }
}




extension ViewController {
    
    func testOperator() {
        /*
         Operator 操作符,用于
         创建新的Observable 对象
         或变换组合原有的 Observable
         */
        let disposeBag = DisposeBag()
        
        Observable.of(2,30,22,5,60,1)
            .filter{$0>10}
            .subscribe(onNext: {print($0)})
            .disposed(by: disposeBag)
        
        
    }
    
    
    
    func testObserver() {
        /*从0 开始发射 10 个数字*/
        let numbers: Observable<Int> = Observable.create { observer -> Disposable in
            observer.onNext(0)
            observer.onNext(1)
            observer.onNext(2)
            observer.onNext(3)
            observer.onNext(4)
            observer.onNext(5)
            observer.onNext(6)
            observer.onNext(7)
            observer.onNext(8)
            observer.onNext(9)
            observer.onCompleted()
            return Disposables.create()
        }
        
        
        numbers.subscribe(onNext: { (number) in
            print(number)
        }, onError: { (error) in
            print("发生错误:\(error.localizedDescription)")
        }, onCompleted: {
            print("任务完成")
        }) {
            
        }
        
        
        
    }
    
    
    
    func testMoyaProvider() {
        /*
         * open class MoyaProvider<Target: TargetType>: MoyaProviderType {}
         * provider 是一个遵循 MayaProviderType 协议的公开类 ,需要传入一个遵循 TargetType 协议的对象名,泛型常规用法
         * extension APIManager:TargetType ,比如之前封装APIManager 的时候扩展里面也是遵循了 TargetType 协议
         */
        
        //        let rxProvider = MoyaProvider<APIManager>()
        
        //        rxProvider.rx.request(.getNbaInfo("537f7b3121a797c8d18f4c0523f3c124")).asObservable().mapResponseToObject(type: Testmodel.self).subscribe { (test) in
        //            print(test)
        //            let model = test.element
        //            print(model?.reason ?? String.self)
        //        }
        //        .disposed(by: disposeBag)
    }
    
    
}


